#ifndef _PROTO_SMART_H_
#define _PROTO_SMART_H_

#include <types.h>
#include <utils.h>



//---------------------------------------------------------------------------------------
/*
 * frame flags
 */
#define STC					0x7E
#ifndef DID_LEN
#define DID_LEN     		0x02
#endif
#define SID_LEN    			0x02
#define AID_LEN     		0x04
#define PANID_LEN			0x02
#define BUF_LEN				0xFF
#define EID_LEN				0x08
#define PW_LEN          	0x02
#define PSK_LEN 			0x08
#define SN_LEN          	0x0C
#define DKEY_LEN        	0x08
#define MAGIC_NUM_LEN		0x04
#define WDATA_NUM			0x0A
#define WDATA_LEN			0x40

//---------------------------------------------------------------------------------------
/*
 * frame command
 */
#define CMD_SET_AID     	0x01
#define CMD_GET_AID     	0x03
#define CMD_ACK_AID     	0x13
#define CMD_DEL_AID     	0x04
#define CMD_REQ_AID     	0x05
#define CMD_GET_SID     	0x06
#define CMD_ACK_SID     	0x16
#define CMD_GET_EID     	0x07
#define CMD_ACK_EID     	0x17
#define CMD_SET_BPS     	0x08
#define CMD_SET_REG     	0x09
#define CMD_UNLINK      	0x0A
#define CMD_REGINFOR    	0x0B
#define CMD_SET_PANID   	0x0C
#define CMD_GET_GWAID   	0x0D
#define CMD_GET_VER     	0x0E
#define CMD_ACK_VER     	0x1E
#define CMD_GET_PANID   	0x0F
#define CMD_ACK_PANID   	0x1F
#define CMD_TST_PLC     	0x20
#define CMD_CHG_TONE    	0x21

#define CMD_ACK         	0x00
#define CMD_NAK         	0xFF

#define CMD_SET         	0x07
#define CMD_GET        		0x02
#define CMD_UPDATE      	0x05
#define CMD_RELI_REPORT     0x01
#define CMD_NRELI_REPORT    0x00

#define CMD_SET_PASSTH		0x28
#define CMD_GET_PASSTH		0x29
#define CMD_ACK_PASSTH		0x39
#define CMD_START_SCH		0xA0
#define CMD_SET_SCH			0xA1

#define PRESSKEY_REG     	0x01
#define PASSWORD_REG     	0x00
#define PASSWORD_ERR     	0x02
//---------------------------------------------------------------------------------------
/*
 * frame error no
 */
#define NO_ERR        		0x00
#define OTHER_ERR     		0x0F
#define LEN_ERR       		0x01
#define BUFFER_ERR    		0x02
#define DATA_ERR      		0x03
#define DID_ERR       		0x04
#define DEV_BUSY      		0x05
#define NO_RETURN     		0x10
#define DATA_TRANS    		0x12

//local contral
#define SINGLE          0x00
#define BROAD           0x01
#define GROUP_LEN       0x3F
/*
 * DID definitions
 */
enum
{
	DID_GETAID       = 0x0605,
    DID_DEVRGST      = 0x0603,
	DID_EXITNET      = 0x060B,
	DID_DEVTYPE      = 0x0001,
	DID_COMMVER      = 0x0002,
	DID_SOFTVER      = 0x0003,
	DID_DEVKEY       = 0x0005,
	DID_DEVSN        = 0x0007,
	DID_PWD		     = 0x000A,
	DID_DEVSHOW      = 0x0009,
	DID_SILENT	     = 0x000B,
	DID_CHKPWD       = 0xC030,
	
	DID_NOBODY_TIME  = 0xD004,
	DID_SENSOR_VALUE = 0xB701,
	DID_REPORT_STEP  = 0xD103,
	DID_REPORT_FREQ  = 0xD104,
	DID_POWER_ON     = 0xD702,
	DID_COMPENSATE   = 0xD106,
	DID_TEST_POWER_ON= 0xFFD7,
	DID_TEST_NOBODY_TIME  = 0xFFD8,
	DID_TEST_SOFT_STATE  = 0xFFA1,
	DID_TEST_HAL_STATE   = 0xFFA2,
	DID_TEST_PIR_AD      = 0xFFA3,
	DID_SWITCHCTRL   = 0xC012,
	//DID_CTRLINFO     = 0xFB20,
	DID_REBOOT    	 = 0xFEFD,
	DID_SENSOR_THR   = 0xD003,
	DID_REPORT_ENABLE= 0xD005,
	DID_TARGET_ADDR  = 0xD006,
	DID_DISCOVER_METER = 0X0014,
};

#pragma pack(1)
typedef struct SmartFrame
{
    uint8_t stc;
    uint8_t said[AID_LEN];
    uint8_t taid[AID_LEN];
    uint8_t seq;
    uint8_t len;
    uint8_t data[1];//data[0]:CMD;          data[1:2]:DID;   data[3]:CTRL;
                    //data[4:len-1]:data    data[len]:sum
} smart_frame_t;
#define SMART_FRAME_HEAD offset_of(smart_frame_t, data)

struct AppFrame
{
    uint8_t cmd;
    uint8_t data[0];
};
struct GroupFrame
{
    uint8_t len : 6;
    uint8_t type: 2;
    uint8_t data[1];
};

typedef struct Body
{
    uint8_t did[DID_LEN];
    uint8_t ctrl;
    uint8_t data[0];
} body_t;
#define FBD_FRAME_HEAD  offset_of(body_t, data)

struct RegData
{
    uint8_t aid[AID_LEN];
    uint8_t panid[SID_LEN];
    uint8_t pw[PW_LEN];
    uint8_t gid[AID_LEN];
    uint8_t sid[SID_LEN];
};


#pragma pack()

static inline int smart_frame_len(const smart_frame_t *frame)
{
    return SMART_FRAME_HEAD + frame->len + 1;
}
static inline bool smart_frame_is_broadcast(const smart_frame_t *frame)
{
    return is_all_xx(frame->taid, 0xff, AID_LEN);
}
static inline bool smart_frame_is_local(const smart_frame_t *pframe)
{
    return is_all_xx(pframe->said, 0x00, AID_LEN) && is_all_xx(pframe->taid, 0x00, AID_LEN);
}
static inline bool smart_frame_is_ack(const smart_frame_t *frame)
{
    return tst_bit(frame->seq, 7);
}
static inline int smart_frame_body_len(const body_t *body);
int smart_frame_is_mine(struct SmartFrame *pframe);
smart_frame_t *get_smart_frame(const uint8_t *in, uint32_t len);
int code_body(uint16_t did, int err, const void *data, int len, void *out, int maxlen);
//int code_frame(const uint8_t *src, const uint8_t *dest, int seq, int cmd, \
//               const uint8_t *data, int len, void *out, int maxlen);
int code_frame(const uint8_t *src, const uint8_t *dest, int seq, int cmd, 
    uint8_t *data, int len, void *out, int maxlen);
int code_local_frame(const uint8_t *in, int len, void *out, int maxlen);
int code_ret_frame(smart_frame_t *pframe, int len);
bool is_gid_equal(const uint8_t *data, uint16_t mysid);
int is_searching_meter(void);
#endif
